package com.xiaogang.ggfw.utils.common;


import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.sql.Timestamp;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;

/**
 * 日期工具类, 继承org.apache.commons.lang.time.DateUtils类
 *
 * @author chengyou
 * @version 2014-4-15
 */
public class DateUtils {
    public static final long weekDay = 7;

    private static String[] parsePatterns = {
            "yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm", "yyyy-MM",
            "yyyy/MM/dd", "yyyy/MM/dd HH:mm:ss", "yyyy/MM/dd HH:mm", "yyyy/MM",
            "yyyy.MM.dd", "yyyy.MM.dd HH:mm:ss", "yyyy.MM.dd HH:mm", "yyyy.MM"};

    /**
     * @return
     */
    public static String formatterCustomDate(Date date) {
        String returnStr;
        SimpleDateFormat dfs = new SimpleDateFormat("yyyy-MM-dd HH:mm");
        try {
            long time = date.getTime();
            long nowTime = System.currentTimeMillis();
            long between = (nowTime - time) / 1000;// 除以1000是为了转换成秒
            if (between <= 60 * 60 || between < 60) {
                int seconds = (int) (between / 60);
                returnStr = ((seconds) == 0 ? 1 : seconds) + "分钟前发布";
            } else if (between < 24 * 60 * 60) {
                returnStr = between / (60 * 60) + "小时前发布";
            } else {
                returnStr = dfs.format(date);
            }
            return returnStr;
        } catch (Exception e) {
            return "";
        }
    }

    /**
     * 得到日期时间字符串，转换格式（yyyy-MM-ddTHH:mm:ssZ）
     */
    public static String formatDateTime4(Date date) {
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
        return formatter.format(date);
    }

    /**
     * 日期型字符串转化为日期 格式
     * { "yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm",
     * "yyyy/MM/dd", "yyyy/MM/dd HH:mm:ss", "yyyy/MM/dd HH:mm",
     * "yyyy.MM.dd", "yyyy.MM.dd HH:mm:ss", "yyyy.MM.dd HH:mm" }
     */
    public static Timestamp parseTimestamp(String str) {
        if (str == null) {
            return null;
        }
        try {
            return Timestamp.valueOf(str);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 获取过去的天数
     *
     * @param date
     * @return
     */
    public static long pastDays(Date date) {
        long t = new Date().getTime() - date.getTime();
        return t / (24 * 60 * 60 * 1000);
    }

    /**
     * 获取过去的小时
     *
     * @param date
     * @return
     */
    public static long pastHour(Date date) {
        long t = new Date().getTime() - date.getTime();
        return t / (60 * 60 * 1000);
    }

    /**
     * 获取过去的分钟
     *
     * @param date
     * @return
     */
    public static long pastMinutes(Date date) {
        long t = new Date().getTime() - date.getTime();
        return t / (60 * 1000);
    }

    /**
     * 获取过去的分钟
     *
     * @param date
     * @return
     */
    public static long getMinutes(Date date) {
        long t = date.getTime();
        return t / (60 * 1000);
    }

    /**
     * 获取utc毫秒值
     *
     * @return
     */
    public static long getUTCCurrentTimeMillis() {
        // 1、取得本地时间：
        Calendar cal = Calendar.getInstance();
        // 2、取得时间偏移量：
        int zoneOffset = cal.get(Calendar.ZONE_OFFSET);
        // 3、取得夏令时差：
        int dstOffset = cal.get(Calendar.DST_OFFSET);
        // 4、从本地时间里扣除这些差量，即可以取得UTC时间：
        cal.add(Calendar.MILLISECOND, -(zoneOffset + dstOffset));
        long utcTime = cal.getTimeInMillis();
//		System.out.println("utc:"+formatDateTime(new Date(utcTime)));
        return utcTime;
    }

    /**
     * 获取当前时间毫秒值
     *
     * @return
     */
    public static long getCurrentTimeMillis() {
        return System.currentTimeMillis();
    }

    /**
     * 转换为时间（天,时:分:秒.毫秒）
     *
     * @param timeMillis
     * @return
     */
    public static String formatDateTime(long timeMillis) {
        long day = timeMillis / (24 * 60 * 60 * 1000);
        long hour = (timeMillis / (60 * 60 * 1000) - day * 24);
        long min = ((timeMillis / (60 * 1000)) - day * 24 * 60 - hour * 60);
        long s = (timeMillis / 1000 - day * 24 * 60 * 60 - hour * 60 * 60 - min * 60);
        long sss = (timeMillis - day * 24 * 60 * 60 * 1000 - hour * 60 * 60 * 1000 - min * 60 * 1000 - s * 1000);
        return (day > 0 ? day + "," : "") + hour + ":" + min + ":" + s + "." + sss;
    }

    /**
     * 获取两个日期之间的天数
     *
     * @param before
     * @param after
     * @return
     */
    public static double getDistanceOfTwoDate(Date before, Date after) {
        long beforeTime = before.getTime();
        long afterTime = after.getTime();
        return (afterTime - beforeTime) / (1000 * 60 * 60 * 24);
    }

    /**
     * 获取两个日期之间的天数(int)
     *
     * @param before
     * @param after
     * @return
     */
    public static int getDistanceOfTwoDateInt(Date before, Date after) {
        int days = (int) ((after.getTime() - before.getTime()) / (1000 * 3600 * 24));
        return days;
    }

    /**
     * 日期比较
     *
     * @param
     * @param
     * @return
     */
    public static int compareDay(Date date1, Date date2) throws Exception {
        DateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        String strDate1 = sdf.format(date1);
        String strDate2 = sdf.format(date2);
        if (sdf.parse(strDate1).getTime() > sdf.parse(strDate2).getTime()) {//转成long类型比较
            return 1;
        } else if (sdf.parse(strDate1).getTime() < sdf.parse(strDate2).getTime()) {
            return -1;
        } else {
            return 0;
        }
    }

    /**
     * 日期加天数
     *
     * @param
     * @param
     * @return
     */
    public static Date addDay(Date date, int addDay) {
        if (date == null) {
            return null;
        }
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.add(Calendar.DATE, addDay);
        return cal.getTime();
    }

    /**
     * 日期加小时
     *
     * @param
     * @param
     * @return
     */
    public static Date getDateAddHour(Date date, int addHour) {
        if (date == null) {
            return null;
        }
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.add(Calendar.HOUR, addHour);//24小时制
        return cal.getTime();
    }

    /**
     * 日期加分钟
     *
     * @param
     * @param
     * @return
     */
    public static Date getDateAddMinute1(Date date, int addMinute) {
        if (date == null) {
            return null;
        }
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.add(Calendar.MINUTE, addMinute);//24小时制
        return cal.getTime();
    }

    /**
     * 检查字符串是否是datatime格式
     *
     * @param timeStr
     * @return
     */
    public static boolean checkDataTimeWithString(String timeStr) {
        boolean dateflag = true;
        if (timeStr == null) {
            return false;
        }

        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        try {
            Date date = format.parse(timeStr);
        } catch (ParseException e) {
            dateflag = false;
        } finally {
            System.out.println("日期是否满足要求" + dateflag);
        }
        return dateflag;
    }

    /**
     * 获取指定年月的第一天
     *
     * @param year
     * @param month
     * @return
     */
    public static String getFirstDayOfMonth1(int year, int month) {
        Calendar cal = Calendar.getInstance();
        //设置年份
        cal.set(Calendar.YEAR, year);
        //设置月份
        cal.set(Calendar.MONTH, month - 1);
        //获取某月最小天数
        int firstDay = cal.getMinimum(Calendar.DATE);
        //设置日历中月份的最小天数
        cal.set(Calendar.DAY_OF_MONTH, firstDay);
        //格式化日期
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        return sdf.format(cal.getTime());
    }

    /**
     * 获取指定年月的最后一天
     *
     * @param year
     * @param month
     * @return
     */
    public static String getLastDayOfMonth1(int year, int month) {
        Calendar cal = Calendar.getInstance();
        //设置年份
        cal.set(Calendar.YEAR, year);
        //设置月份
        cal.set(Calendar.MONTH, month - 1);
        //获取某月最大天数
        int lastDay = cal.getActualMaximum(Calendar.DATE);
        //设置日历中月份的最大天数
        cal.set(Calendar.DAY_OF_MONTH, lastDay);
        //格式化日期
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        return sdf.format(cal.getTime());
    }


    /**
     * 获取指定周的第一天和最后一天
     *
     * @param dataStr
     * @return
     * @throws ParseException
     */
    public static String getFirstOfWeek(String dataStr) {
        Calendar cal = Calendar.getInstance();

        try {
            cal.setTime(new SimpleDateFormat("yyyy-MM-dd").parse(dataStr));
        } catch (ParseException e) {
            e.printStackTrace();
        }

        int d = 0;
        if (cal.get(Calendar.DAY_OF_WEEK) == 1) {
            d = -6;
        } else {
            d = 2 - cal.get(Calendar.DAY_OF_WEEK);
        }
        cal.add(Calendar.DAY_OF_WEEK, d);
        // 所在周开始日期
        String data1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(cal.getTime());
        cal.add(Calendar.DAY_OF_WEEK, 6);
        return data1;

    }


    /**
     * 得到该日期下本周第一天
     *
     * @param time
     * @return
     */
    private static String getWeekByDate(Date time) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); // 设置时间格式
        Calendar cal = Calendar.getInstance();
        cal.setTime(time);
        // 判断要计算的日期是否是周日，如果是则减一天计算周六的，否则会出问题，计算到下一周去了
        int dayWeek = cal.get(Calendar.DAY_OF_WEEK);// 获得当前日期是一个星期的第几天
        if (1 == dayWeek) {
            cal.add(Calendar.DAY_OF_MONTH, -1);
        }
        cal.setFirstDayOfWeek(Calendar.MONDAY);// 设置一个星期的第一天，按中国的习惯一个星期的第一天是星期一
        int day = cal.get(Calendar.DAY_OF_WEEK);// 获得当前日期是一个星期的第几天
        cal.add(Calendar.DATE, cal.getFirstDayOfWeek() - day);// 根据日历的规则，给当前日期减去星期几与一个星期第一天的差值
        System.out.println("所在周星期一的日期：" + sdf.format(cal.getTime()));
        return sdf.format(cal.getTime());
    }


    /**
     * 获取date该日期下的
     * weekDay 7天前的日期
     *
     * @param dateStr
     * @return
     * @throws
     */
    public static String getDayMinusDate(String dateStr) {

        SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd");
        Date date = null;
        try {
            date = sf.parse(dateStr);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return sf.format(minusDate(date, weekDay)) + " 00:00:00";
    }

    private static Date minusDate(Date date, long day) {
        long time = date.getTime(); // 得到指定日期的毫秒数
        day = day * 24 * 60 * 60 * 1000; // 要加上的天数转换成毫秒数
        return new Date(time - day); // 相减 并将毫秒数转换成日期
    }


    /**
     * 获取utc毫秒值
     *
     * @return
     */
    public static long getChinaTimeMillis() {
        return getCurrentTimeMillisBYTimeZone(8);
    }

    /**
     * 获取utc毫秒值
     *
     * @return
     */
    public static long getChinaTimeMillis2() {
        Calendar cal = Calendar.getInstance(Locale.CHINA);
        long longTime = cal.getTimeInMillis();
        return longTime;
    }

    /**
     * 获取某时区毫秒值
     *
     * @return
     */
    public static long getCurrentTimeMillisBYTimeZone(Integer timeZone) {
        String timeZoneStr = "GMT-" + timeZone + ":00";
        //取得指定时区的时间：　　　　　　
        TimeZone zone = TimeZone.getTimeZone(timeZoneStr);
        Calendar cal = Calendar.getInstance(zone);
        long longTime = cal.getTimeInMillis();
        return longTime;
    }

    /**
     * 根据传入时间判断当天是否为本月最后一个工作日
     *
     * @param date
     * @return
     */
    public static boolean isLastWorkingDay(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.clear();
        cal.setTime(date);
        // 得到今天是本月的几号
        int today = cal.get(Calendar.DAY_OF_MONTH);
        // 得到本月最后一天是几号
        int lastDay = cal.getActualMaximum(Calendar.DAY_OF_MONTH);
        // 通过循环调用api.goseek.cn提供的api查询出本月的最后一个工作日是几号
        for (; lastDay >= 1; lastDay--) {
            boolean flag = false;
            cal.set(Calendar.DAY_OF_MONTH, lastDay);
            SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
            // 该api返回数据中倒数第二位字符：为0则表示正常工作日，为1则表示国家法定节假日，为2则表示节假日调休补班，为3则表示周末
            String httpUrl = "http://api.goseek.cn/Tools/holiday?date=" + sdf.format(cal.getTime());
            BufferedReader reader = null;
            String result = null;
            StringBuffer sbf = new StringBuffer();
            // 调用api，创建get请求
            try {
                URL url = new URL(httpUrl);
                HttpURLConnection connection = (HttpURLConnection) url.openConnection();
                connection.setRequestMethod("GET");
                connection.connect();
                // 得到返回的InputStream
                InputStream is = connection.getInputStream();
                reader = new BufferedReader(new InputStreamReader(is, "UTF-8"));
                String strRead = null;
                if ((strRead = reader.readLine()) != null) {
                    sbf.append(strRead);
                }
                reader.close();
                result = sbf.toString();
                char[] charArray = result.toCharArray();
                // 正常工作日情况
                if (charArray[charArray.length - 2] == '0') {
                    flag = true;
                }
                // 调休补班的情况
                else if (charArray[charArray.length - 2] == '2') {
                    flag = true;
                }
                // 确定本月最后工作日，判断是否等于今日
                if (flag) {
                    if (today == lastDay) {
                        return true;
                    } else {
                        break;
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return false;
    }


    /**
     * 获取给定日期的第二天凌晨日期 例如：2018-09-21 11:22:33 返回：2018-09-22 00:00:00
     *
     * @param dateTime
     * @return
     */
    public static Date getNextDay(String dateTime) {
        SimpleDateFormat simpleDateFormat = new
                SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Calendar calendar = Calendar.getInstance();
        try {
            Date date = simpleDateFormat.parse(dateTime);
            calendar.setTime(date);
            calendar.add(Calendar.DATE, 1);
            calendar.set(Calendar.HOUR_OF_DAY, 0);
            calendar.set(Calendar.MINUTE, 0);
            calendar.set(Calendar.SECOND, 0);
        } catch (ParseException e) {
            System.out.println("Date format error!!!!");
        }
        return calendar.getTime();
    }

    public static Double dateDiff(String startTime, String endTime, String format) throws Exception {
        //按照传入的格式生成一个simpledateformate对象
        SimpleDateFormat sd = new SimpleDateFormat(format);
        long nd = 1000*24*60*60;//一天的毫秒数
        long nh = 1000*60*60;//一小时的毫秒数
        long nm = 1000*60;//一分钟的毫秒数
        long ns = 1000;//一秒钟的毫秒数
        long diff;
        //获得两个时间的毫秒时间差异
        diff = sd.parse(endTime).getTime() - sd.parse(startTime).getTime();
        long day = diff/nd;//计算差多少天
        long hour = diff%nd/nh;//计算差多少小时
        long min = diff%nd%nh/nm;//计算差多少分钟
        long sec = diff%nd%nh%nm/ns;//计算差多少秒//输出结果
        System.out.println("时间相差："+day+"天"+hour+"小时"+min+"分钟"+sec+"秒。");
        Double mins = 0.0;
        Double secs= 0.0;
        if (min>0){
            mins = (double)min/60;
        }
        if (sec>=30){
            secs = 0.1;
        }
        return day * 24 + hour +mins + secs;
    }


    /**
     * 时间处理
     * @param time 要处理的时间
     * @param type 当type为0时增  为其他值时减
     * @param soure 秒数
     * @return
     */
    public static Date timeDisposal(SimpleDateFormat df,String time,Integer type,Integer soure) {
        Date dateTime = null;
        try{
            Date date =df.parse(time);
            if (type == 0){
                date.setTime(date.getTime() + soure * 1000);
            }else{
                date.setTime(date.getTime() - soure * 1000);
            }
            dateTime = df.parse(df.format(date));
        }catch (Exception e){
            return null;
        }
        return dateTime;
    }
}
